#include "common_def.h"
#include "soc_osal.h"
#include "securec.h"
#include "product.h"
#include "bts_le_gap.h"
#include "cmsis_os2.h"
#include "time.h"
#include "stdlib.h"
#include "gpio.h"
#include "hal_gpio.h"
#include "tcxo.h"
#include "app_init.h"
#include "pinctrl.h"

#include "sle_connection_manager.h"
#include "sle_device_discovery.h"
#include "sle_errcode.h"

#include "sle_server_adv.h"

#include "seat.h"
#include "sensor.h"
#include "task.h"

#define SLE_SERVER_LOG "[sle uart server]"

uint8_t g_sle_local_name[NAME_MAX_LENGTH] = "sle_server";
uint8_t local_addr[SLE_ADDR_LEN] = {0x13, 0x67, 0x5c, 0x07, 0x00, 0x01};
sle_announce_seek_callbacks_t announce_cbks = {0};

uint16_t sle_set_adv_local_name(uint8_t *adv_data, uint16_t max_len)
{
    errcode_sle_t ret;
    uint8_t index = 0;
    uint8_t *local_name = g_sle_local_name;
    uint8_t local_name_len = sizeof(g_sle_local_name) - 1;
    osal_printk("%s local_name_len = %d\r\n", SLE_SERVER_LOG, local_name_len);
    osal_printk("%s local_name: ", SLE_SERVER_LOG);
    for (uint8_t i = 0; i < local_name_len; i++)
    {
        osal_printk("0x%02x ", local_name[i]);
    }
    osal_printk("\r\n");
    adv_data[index++] = local_name_len + 1;
    adv_data[index++] = SLE_ADV_DATA_TYPE_COMPLETE_LOCAL_NAME;
    ret = memcpy_s(&adv_data[index], max_len - index, local_name, local_name_len);
    if (ret != EOK)
    {
        osal_printk("%s memcpy fail\r\n", SLE_SERVER_LOG);
        return 0;
    }
    return (uint16_t)index + local_name_len;
}

uint16_t sle_set_adv_data(uint8_t *adv_data)
{
    size_t len = 0;
    uint16_t idx = 0;
    errcode_sle_t ret = 0;

    len = sizeof(struct sle_adv_common_value);
    struct sle_adv_common_value adv_disc_level = {
        .length = len - 1,
        .type = SLE_ADV_DATA_TYPE_DISCOVERY_LEVEL,
        .value = SLE_ANNOUNCE_LEVEL_NORMAL,
    };
    ret = memcpy_s(&adv_data[idx], SLE_ADV_DATA_LEN_MAX - idx, &adv_disc_level, len);
    if (ret != EOK)
    {
        osal_printk("%s adv_disc_level memcpy fail\r\n", SLE_SERVER_LOG);
        return 0;
    }
    idx += len;

    len = sizeof(struct sle_adv_common_value);
    struct sle_adv_common_value adv_access_mode = {
        .length = len - 1,
        .type = SLE_ADV_DATA_TYPE_ACCESS_MODE,
        .value = 0,
    };
    ret = memcpy_s(&adv_data[idx], SLE_ADV_DATA_LEN_MAX - idx, &adv_access_mode, len);
    if (ret != EOK)
    {
        osal_printk("%s adv_access_mode memcpy fail\r\n", SLE_SERVER_LOG);
        return 0;
    }
    idx += len;

    return idx;
}

uint16_t sle_set_scan_response_data(uint8_t *scan_rsp_data)
{
    uint16_t idx = 0;
    errcode_sle_t ret;
    size_t scan_rsp_data_len = sizeof(struct sle_adv_common_value);

    struct sle_adv_common_value tx_power_level = {
        .length = scan_rsp_data_len - 1,
        .type = SLE_ADV_DATA_TYPE_TX_POWER_LEVEL,
        .value = SLE_ADV_TX_POWER,
    };
    ret = memcpy_s(scan_rsp_data, SLE_ADV_DATA_LEN_MAX, &tx_power_level, scan_rsp_data_len);
    if (ret != EOK)
    {
        osal_printk("%s sle scan response data memcpy fail\r\n", SLE_SERVER_LOG);
        return 0;
    }
    idx += scan_rsp_data_len;

    /* set local name */
    idx += sle_set_adv_local_name(&scan_rsp_data[idx], SLE_ADV_DATA_LEN_MAX - idx);
    return idx;
}

int sle_set_default_announce_param(void)
{
    errcode_sle_t ret;
    // 设置设备公开参数
    sle_announce_param_t param = {0};
    uint8_t index;
    // generate_random_local_addr(local_addr);//错误：烧录后地址一样
    param.announce_mode = SLE_ANNOUNCE_MODE_CONNECTABLE_SCANABLE;
    param.announce_handle = SLE_ADV_HANDLE_DEFAULT;
    param.announce_gt_role = SLE_ANNOUNCE_ROLE_T_CAN_NEGO;
    param.announce_level = SLE_ANNOUNCE_LEVEL_NORMAL;
    param.announce_channel_map = SLE_ADV_CHANNEL_MAP_DEFAULT;
    param.announce_interval_min = SLE_ADV_INTERVAL_MIN_DEFAULT;
    param.announce_interval_max = SLE_ADV_INTERVAL_MAX_DEFAULT;
    param.conn_interval_min = SLE_CONN_INTV_MIN_DEFAULT;
    param.conn_interval_max = SLE_CONN_INTV_MAX_DEFAULT;
    param.conn_max_latency = SLE_CONN_MAX_LATENCY;
    param.conn_supervision_timeout = SLE_CONN_SUPERVISION_TIMEOUT_DEFAULT;
    param.announce_tx_power = 18;
    param.own_addr.type = 0;
    ret = memcpy_s(param.own_addr.addr, SLE_ADDR_LEN, local_addr, SLE_ADDR_LEN);
    if (ret != EOK)
    {
        osal_printk("%s sle_set_default_announce_param data memcpy fail\r\n", SLE_SERVER_LOG);
        return 0;
    }
    osal_printk("%s sle_local addr: ", SLE_SERVER_LOG);
    for (index = 0; index < SLE_ADDR_LEN; index++)
    {
        osal_printk("0x%02x ", param.own_addr.addr[index]);
    }
    osal_printk("\r\n");
    return sle_set_announce_param(param.announce_handle, &param);
}

int sle_set_default_announce_data(void)
{
    errcode_sle_t ret;
    uint8_t announce_data_len = 0;
    uint8_t seek_data_len = 0;
    // 设置设备公开数据
    sle_announce_data_t data = {0};
    uint8_t adv_handle = SLE_ADV_HANDLE_DEFAULT;
    uint8_t announce_data[SLE_ADV_DATA_LEN_MAX] = {0};
    uint8_t seek_rsp_data[SLE_ADV_DATA_LEN_MAX] = {0};
    uint8_t data_index = 0;

    announce_data_len = sle_set_adv_data(announce_data);
    data.announce_data = announce_data;
    data.announce_data_len = announce_data_len;

    osal_printk("%s data.announce_data_len = %d\r\n", SLE_SERVER_LOG, data.announce_data_len);
    osal_printk("%s data.announce_data: ", SLE_SERVER_LOG);
    for (data_index = 0; data_index < data.announce_data_len; data_index++)
    {
        osal_printk("0x%02x ", data.announce_data[data_index]);
    }
    osal_printk("\r\n");

    seek_data_len = sle_set_scan_response_data(seek_rsp_data);
    data.seek_rsp_data = seek_rsp_data;
    data.seek_rsp_data_len = seek_data_len;

    osal_printk("%s data.seek_rsp_data_len = %d\r\n", SLE_SERVER_LOG, data.seek_rsp_data_len);
    osal_printk("%s data.seek_rsp_data: ", SLE_SERVER_LOG);
    for (data_index = 0; data_index < data.seek_rsp_data_len; data_index++)
    {
        osal_printk("0x%02x ", data.seek_rsp_data[data_index]);
    }
    osal_printk("\r\n");

    ret = sle_set_announce_data(adv_handle, &data);
    if (ret == ERRCODE_SLE_SUCCESS)
    {
        osal_printk("%s set announce data success.\r\n", SLE_SERVER_LOG);
    }
    else
    {
        osal_printk("%s set adv param fail.\r\n", SLE_SERVER_LOG);
    }
    return ERRCODE_SLE_SUCCESS;
}

void sle_server_announce_enable_cbk(uint32_t announce_id, errcode_sle_t status)
{
    osal_printk("%s sle announce enable callback id:%02x, state:%x\r\n", SLE_SERVER_LOG, announce_id,
                status);
}

void sle_server_announce_disable_cbk(uint32_t announce_id, errcode_sle_t status)
{
    osal_printk("%s sle announce disable callback id:%02x, state:%x\r\n", SLE_SERVER_LOG, announce_id,
                status);
}

void sle_server_announce_terminal_cbk(uint32_t announce_id)
{
    osal_printk("%s sle announce terminal callback id:%02x\r\n", SLE_SERVER_LOG, announce_id);

    // fan
    osal_task *fan_task = NULL;
    fan_task = osal_kthread_create((osal_kthread_handler)FanTestTask, 0, "FanTask",
                                      FAN_TASK_STACK_SIZE);
    if (fan_task != NULL) {
        osal_kthread_set_priority(fan_task, FAN_TASK_PRIO);
    }
    else {
        osal_printk("FanTask Fail\n");
    }

    //wiper
    osal_task *wiper_task = NULL;
    wiper_task = osal_kthread_create((osal_kthread_handler)WiperTestTask, 0, "WiperTask",
                                      WIPER_TASK_STACK_SIZE);
    if (wiper_task != NULL) {
        osal_kthread_set_priority(wiper_task, WIPER_TASK_PRIO);
    }
    else {
        osal_printk("WiperTask fail\n");
    }

    // feeling light
    osal_task *feeling_task = NULL;
    feeling_task = osal_kthread_create((osal_kthread_handler)FeelingTestTask, 0, "FeelingTask",
                                      FEELING_TASK_STACK_SIZE);
    if (feeling_task != NULL) {
        osal_kthread_set_priority(feeling_task, FEELING_TASK_PRIO);
    }
    else {
        osal_printk("FeelingTask Fail\n");
    }

    // auto light
    osal_task *auto_task = NULL;
    auto_task = osal_kthread_create((osal_kthread_handler)AutoTask, 0, "AutoTask",
                                      AUTO_TASK_STACK_SIZE);
    if (auto_task != NULL) {
        osal_kthread_set_priority(auto_task, AUTO_TASK_PRIO);
    }
    else {
        osal_printk("AutoTask fail\n");
    }

    //sensor
    osal_task *sensor_task = NULL;
    sensor_task = osal_kthread_create((osal_kthread_handler)Sensor_Task, 0, "SensorTask",
                                      FAN_TASK_STACK_SIZE);
    if (sensor_task != NULL) {
        osal_kthread_set_priority(sensor_task, FAN_TASK_PRIO);
    }
    else {
        osal_printk("sensortask fail\n");
    }
    
    // seat
    osal_task *seat_task = NULL;
    seat_task = osal_kthread_create((osal_kthread_handler)Seat_Task, 0, "SeatTask",
                                      SEAT_TASK_STACK_SIZE);
    if (seat_task != NULL) {
        osal_kthread_set_priority(seat_task, SEAT_TASK_PRIO);
    }
    else {
        osal_printk("seattask fail\n");
    }
}

void sle_s_enable_cbk(errcode_sle_t status)
{
    osal_printk("sle enable status:%02x\r\n", status);
}

errcode_sle_t sle_announce_register(void)
{
    sle_announce_seek_callbacks_t sle_announce_cbks;
    sle_announce_cbks.announce_enable_cb = sle_server_announce_enable_cbk;
    sle_announce_cbks.announce_disable_cb = sle_server_announce_disable_cbk;
    sle_announce_cbks.announce_terminal_cb = sle_server_announce_terminal_cbk;
    sle_announce_cbks.sle_enable_cb = sle_s_enable_cbk;
    return sle_announce_seek_register_callbacks(&sle_announce_cbks);
}

errcode_sle_t sle_server_adv_init(void)
{
    errcode_sle_t ret;
    sle_set_default_announce_param();                 // 设置设备公开参数
    sle_set_default_announce_data();                  // 设置设备公开数据
    ret = sle_start_announce(SLE_ADV_HANDLE_DEFAULT); // 开启设备公开
    if (ret != ERRCODE_SLE_SUCCESS)
    {
        osal_printk("%s sle_server_adv_init,sle_start_announce fail :%x\r\n", SLE_SERVER_LOG, ret);
        return ret;
    }
    return ERRCODE_SLE_SUCCESS;  
}